package org.vsg.common.pagination.web.taglibs;

import java.util.logging.Logger;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyTagSupport;
import javax.servlet.jsp.tagext.IterationTag;
import javax.servlet.jsp.tagext.Tag;

import org.vsg.common.pagination.AdvancedPagination;
import org.vsg.common.pagination.Pagination;
import org.vsg.common.pagination.wrapper.GenericWebPaginationWrapper;
import org.vsg.common.pagination.wrapper.GenericWebSortByPaginationWrapper;

/**
 * JSP Tag Handler class
 *
 * @jsp.tag   name = "PageNumber"
 *            display-name = "Name for PageNumber"
 *            description = "Description for PageNumber"
 *            body-content = "JSP"
 */
public class PageNumberTag extends BodyTagSupport {

	private Logger logger = Logger.getLogger(this.getClass().toString());	
	
	/**
	 * get the total pages
	 */
	private int totalPages;
	
	private PaginationBarTag parent;
	
	/**
	 * that will defined view mode,"grouping" or "all",default "all", 
	 */
	private String viewMode = "all";
	
	/**
	 * show reference pageindex
	 */
	private int pageIndexNum;
	
	// set the defined
	private int groupingSize;
	
	
	/**
	 * @return Returns the viewMode.
	 */
	public String getViewMode() {
		return viewMode;
	}


	/**
	 * @param viewMode The viewMode to set.
	 */
	public void setViewMode(String viewMode) {
		this.viewMode = viewMode;
	}


	public int doStartTag() throws JspException {
		// initialize page group count index
		int groupingCountIndex = 0;
		this.setValue("groupingCountIndex",new Integer(groupingCountIndex));
		
		parent = (PaginationBarTag)this.findAncestorWithClass(this,PaginationBarTag.class);
		
		if (parent == null) {
			throw new JspException("Element \"Page Number\" must set in the element \"paginationBar\"! ");
		}
		
		Pagination page = parent.getPagination();
		totalPages = page.getTotalPages();
		pageIndexNum = 0;
		int pageNum = 0;
		
		Object wrapper = pageContext.getAttribute(parent.getId());
		StringBuffer pageNumberUrl = new StringBuffer();
		
		// use group model
		if (viewMode.toLowerCase().equals("group")) {
			if (!(page instanceof AdvancedPagination)) {
				logger.info("The Pagination instance did not supported!");
			}
			
			// set the value
			else {
				AdvancedPagination apage = (AdvancedPagination)page;
				groupingSize = apage.getGroupingSize();
				int tempGroupingStartIndex = apage.getPageIndex() / apage.getGroupingSize();
				tempGroupingStartIndex = tempGroupingStartIndex * apage.getGroupingSize();
				pageIndexNum = tempGroupingStartIndex;
			}
		}

		if (wrapper instanceof GenericWebSortByPaginationWrapper) {
			GenericWebSortByPaginationWrapper webWrapper = (GenericWebSortByPaginationWrapper)wrapper;
			pageNum = webWrapper.getNumPage(pageIndexNum);

			// get the total record is not empty
			if (page.getTotalRecord() > 0) {
				pageNumberUrl.append(webWrapper.getNumPageUrl(pageIndexNum));
				pageIndexNum++;
			} else {
				pageNumberUrl.append(webWrapper.getNumPageUrl(pageIndexNum));
			}
			
			pageContext.setAttribute("pageNumber",new Integer(pageNum));
			pageContext.setAttribute("pageNumberUrl", pageNumberUrl.toString());

		}		
		else if (wrapper instanceof GenericWebPaginationWrapper) {
			GenericWebPaginationWrapper webWrapper = (GenericWebPaginationWrapper)wrapper;
			pageNum = webWrapper.getNumPage(pageIndexNum);
			
			// get the total record is not empty
			if (page.getTotalRecord() > 0) {
				pageNumberUrl.append(webWrapper.getNumPageUrl(pageIndexNum));
				pageIndexNum++;
			}
			
			pageContext.setAttribute("pageNumber",new Integer(pageNum));
			pageContext.setAttribute("pageNumberUrl", pageNumberUrl.toString());			
		}
		
		return BodyTagSupport.EVAL_BODY_BUFFERED;
	}
	
	
	public int doAfterBody() throws JspException {
		int returnValue = Tag.SKIP_BODY;
		if (this.bodyContent != null) {
			JspWriter write = this.bodyContent.getEnclosingWriter();
			try {
				write.write(this.bodyContent.getString());
			} catch (Exception e) {
				throw new JspException(e);				
			}
			this.bodyContent.clearBody();			
		}
		


		if (viewMode.toLowerCase().equals("group")) {
			returnValue = groupViewModeInAfterBody();

		}
		
		else if (viewMode.toLowerCase().equals("all")) {
			returnValue = allViewModeInAfterBody();
		}


		return returnValue;
	}
	
	private int allViewModeInAfterBody() throws JspException {
		int returnValue = Tag.SKIP_BODY;
		if (pageIndexNum >= totalPages) {
			returnValue = Tag.SKIP_BODY;
		} else {
			Object wrapper = pageContext.getAttribute(parent.getId());
			StringBuffer pageNumberUrl = new StringBuffer();			
			int pageNum = 0;

			if (wrapper instanceof GenericWebSortByPaginationWrapper) {
				GenericWebSortByPaginationWrapper webWrapper = (GenericWebSortByPaginationWrapper)wrapper;
				pageNum = webWrapper.getNumPage(pageIndexNum);
	
				pageNumberUrl.append(webWrapper.getNumPageUrl(pageIndexNum));
				
				pageContext.setAttribute("pageNumber",new Integer(pageNum));
				pageContext.setAttribute("pageNumberUrl", pageNumberUrl.toString());

			}			
			
			else if (wrapper instanceof GenericWebPaginationWrapper) {
				GenericWebPaginationWrapper webWrapper = (GenericWebPaginationWrapper)wrapper;
				
				pageNum = webWrapper.getNumPage(pageIndexNum);
				pageNumberUrl.append(webWrapper.getNumPageUrl(pageIndexNum));
				
				pageContext.setAttribute("pageNumber",new Integer(pageNum));
				pageContext.setAttribute("pageNumberUrl", pageNumberUrl.toString());
			}
			pageIndexNum++;
			returnValue = IterationTag.EVAL_BODY_AGAIN;
		}
		return returnValue;
	}
	
	private int groupViewModeInAfterBody() throws JspException {
		
		int returnValue = Tag.SKIP_BODY;
		int groupingCountIndex = ((Integer)this.getValue("groupingCountIndex")).intValue();

		if (pageIndexNum >= totalPages) {
			returnValue = Tag.SKIP_BODY;
		} else {
			Object wrapper = pageContext.getAttribute(parent.getId());
			StringBuffer pageNumberUrl = new StringBuffer();			
			int pageNum = 0;

			if (wrapper instanceof GenericWebSortByPaginationWrapper) {
				GenericWebSortByPaginationWrapper webWrapper = (GenericWebSortByPaginationWrapper)wrapper;
				pageNum = webWrapper.getNumPage(pageIndexNum);
	
				pageNumberUrl.append(webWrapper.getNumPageUrl(pageIndexNum));
				
				pageContext.setAttribute("pageNumber",new Integer(pageNum));
				pageContext.setAttribute("pageNumberUrl", pageNumberUrl.toString());

			}			
			
			else if (wrapper instanceof GenericWebPaginationWrapper) {
				GenericWebPaginationWrapper webWrapper = (GenericWebPaginationWrapper)wrapper;
				
				pageNum = webWrapper.getNumPage(pageIndexNum);
				pageNumberUrl.append(webWrapper.getNumPageUrl(pageIndexNum));
				
				pageContext.setAttribute("pageNumber",new Integer(pageNum));
				pageContext.setAttribute("pageNumberUrl", pageNumberUrl.toString());
			}
			
			groupingCountIndex++;
			pageIndexNum++;
			
			if (groupingCountIndex >= groupingSize) {
				// reset grouping size index
				groupingCountIndex = 0;
				returnValue = SKIP_BODY;
			} else {
				returnValue = IterationTag.EVAL_BODY_AGAIN;	
			}
			
			// set the data to value
			this.setValue("groupingCountIndex",new Integer(groupingCountIndex));
			
					
		}
		return returnValue;
		
	}
	
	

}
